// 函数表达式声明 也叫做函数类型推论
let myAddFn: (x: number, y: number) => number = function (x, y) {
  return x * y
}

// 使用箭头函数 不过这么写可读性差
let addFn: (x: number, y: number) => number = (x, y) => x + y;

// 可选参数和默认参数
function testFn(x: number, y?: number): void {
  console.log(x, y);
}

testFn(1);
testFn(1, 2);
// testFn(1, 2, 3); 这就没法进行编译 只能少 不能多

// 剩余参数 和 js 类似 但是可以给它限定数组类型
function restArg(x: number, ...rest: string[]): void {
  console.log(x, ...rest);
}

// this 指向：和 ES6 一样，普通函数则指向调用者
// 箭头函数指向生成箭头函数的环境

// 泛型 不固定类型 可以接收当前的类型，也可以接受未来的某些个类型
function identty<T>(arg: T): T {
  return arg;
}
identty(1); // 传入 number => T:number 所以此时 T 就是 number 类型
identty('你好'); // 这时候 T 就是字符串

// 泛型类 只能用于实例 无法用于 static 修饰的变量或方法
class Gen<T>{
  x: T
  add: (m: T, n: T) => T;
}

let gen = new Gen<number>();
gen.x = 1;
gen.add = (x, y) => {
  return x + y
}

// 泛型约束 使用 extends 来约束泛型的范围
interface Lengthwise {
  length: number;
}
